
#ifndef SX_GRAPHICS_OBJECT_ARCHETYPE_H
#define SX_GRAPHICS_OBJECT_ARCHETYPE_H

#include <sxGraphicsObject.h>
#include <sxGraphicsArchetype.h>
#include <sxGraphicsObjectRenderer.h>
#include <sxGeometricRepresentation.h>

/* Implemented Interfaces */
#include <sxPickable.h>
#include <sxIntersectable.h>

/* Sx library types. */
using Sx::Graphics::Objects::Rendering::RendererImplementation;
using Sx::Graphics::Picking::Pickable;
using Sx::Math::Intersectable;

namespace Sx {
namespace Graphics {
namespace Archetypes {
namespace Objects {

/*
 * The most common form of graphics representation is a geometric component
 * represented by vertices or points in space. Typically the points in space
 * are represented by vectors in three dimensions and are usually used as a
 * basis upon which surface and edge information is built. The GeometricObject
 * archetype represents these basic types of graphics objects. To quickly
 * summarize: 
 *
 *   A GeometricObject_Archetype allows you to pair an abstract object with
 *   a typical geometric representation (3D points) and a renderer.
 *
 * The object is domain specific, hence the templated type, but it must belong
 * to the GraphicsObject hierarchy. The GraphicsObject contains the basic
 * functionality that is required (or useful) for all graphics objects that
 * can be drawn to a screen.
 *
 * When extending the GeometricObject_Archetype to define a new archetype for
 * a new abstract object type, the archetype must provide the communication
 * between the object and its physical representation. Client code does not
 * have to re-implement the entire interface of the GraphicsObjectType but
 * does have to implement any functions that also change the state of the
 * physical representation.
 */
template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
class GeometricObject_Archetype : public GraphicsArchetype<GraphicsObjectType, RendererImplementation, Real, PhysicalRepresentation>, public Pickable, public Intersectable {

	/*
	 * Any object that will be defined as the template type for this class must
	 * extend the GraphicsObject class. This is due to the definition of the
	 * RendererImplementation which states that it will provide a renderer for
	 * any object extending the GraphicsObject class.
	 */
	static_assert(std::is_base_of<GraphicsObject, GraphicsObjectType>::value, "[GeometricObject_Archetype] Compile Error: GraphicsObjectType must extend class GraphicsObject.");
	static_assert(std::is_base_of<AbstractGeometricRepresentation<Real>, PhysicalRepresentation>::value, "[GeometricObject_Archetype] Compile Error: PhysicalRepresentation must extend class GeometricRepresentation.");

public:
	/*
	 * Public Access to the Instantiated types in this archetype. These type
	 * definitions should only be used when they can be relied on.
	 */
	typedef RendererImplementation RendererType;
	typedef GraphicsObjectType ObjectType;
	typedef PhysicalRepresentation PhysicalRepresentationType;

	/* 
	 * Constructs a new Geometric Object Archetype from the provided object,
	 * renderer, and physical implementation. All of the pointers become owned
	 * by this archetype. The typical extension of the GeoemtricObject_Archetype
	 * is done by sub-classing it and then providing the type of object that
	 * will be used by the archetype. For example:
	 *   class My_Archetype : public GeometricObject_Archetype<MyType> {};
	 *
	 * This class also enforces all sub-classes to implement a constructor
	 * that defines the object, renderer, and physical representation.
	 * Typically these can be initialized from the sub-class constructor:
	 *   My_Archetype(MyRenderer* r) :
	 *     GeometricObject_Archetype(new MyType(), r, new MyRepresentation());
	 */
	GeometricObject_Archetype(const std::shared_ptr<GraphicsObjectType>& object, const std::shared_ptr<RendererImplementation>& renderer, const std::shared_ptr<PhysicalRepresentation>& physicalRepresentation);
	virtual ~GeometricObject_Archetype();

	/*
	 * Important Note: The GeometricObject_Archetype performs the default
	 * GraphicsArchetype construct (calls the internal object's construct, the
	 * physical representation's construct, and then the renderer's construct).
	 * 
	 * If a geometric object's abstract representation is used to generate the
	 * physical representation of that object then overwrite this function
	 * and generate the physical representation data from the object.
	 */
	virtual bool construct();
	virtual void update(Real dt) const;

	/* Pickable override pass-through */
	virtual bool pick(const Eigen::Vector3f& pickSegmentStart, const Eigen::Vector3f& pickSegmentEnd, Eigen::Vector3f& intersectionPoint) = 0;

	/* Intersectable override pass-through */
	virtual bool intersect(const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segment_p1, Eigen::Vector3f& intersectionPoint) = 0;

	/*
	 * Pass-through of the GraphicsObject implementation.
	 */
	bool addPositionX(float x);
	bool addPositionY(float y);
	bool addPositionZ(float z);
	bool addPosition(float x, float y, float z);
	bool addPosition(const Eigen::Vector3f& displacement);
	bool setPositionX(float x);
	bool setPositionY(float y);
	bool setPositionZ(float z);
	bool setPosition(float x, float y, float z);
	bool setPosition(const Eigen::Vector3f& position);
	bool addRotationX(float angle);
	bool addRotationY(float angle);
	bool addRotationZ(float angle);
	bool addRotation(const Eigen::Quaternionf& rotation);
	bool addScaleX(float x);
	bool addScaleY(float y);
	bool addScaleZ(float z);
	bool addScale(float x, float y, float z);
	bool addScale(const Eigen::Vector3f& scale);
	bool setScaleX(float x);
	bool setScaleY(float y);
	bool setScaleZ(float z);
	bool setScale(float x, float y, float z);
	bool setScale(const Eigen::Vector3f& scale);

	float getPositionX() const;
	float getPositionY() const;
	float getPositionZ() const;
	Eigen::Vector3f getPosition() const;
	float getScaleX() const;
	float getScaleY() const;
	float getScaleZ() const;
	Eigen::Vector3f getScale() const;
	Eigen::Quaternionf getRotation() const;

	Color4f getColor() const;
	Color3f getColorSolid() const;

	/* Implementation of the GraphicsObject interface */
	void setName(const String& name);
	void setVisible(bool visible);
	void setSelected(bool selected);
	void setPointSelectionDistance(float distance);
	void setLineSelectionDistance(float distance);
	void show();
	void hide();
	void select();
	void deselect();

	float getPointSelectionDistance() const;
	float getLineSelectionDistance() const;
	bool isSelected() const;
	bool isVisible() const;
	String getName() const;

	void transformPointToLocal(const Eigen::Vector3f& worldPoint, Eigen::Vector3f& localPoint);
	void transformLineToLocal(const Eigen::Vector3f& wPoint0, const Eigen::Vector3f& wPoint1, Eigen::Vector3f& lPoint0, Eigen::Vector3f& lPoint1);
};

}

}

}

}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::GeometricObject_Archetype(const std::shared_ptr<GraphicsObjectType>& object, const std::shared_ptr<RendererImplementation>& renderer, const std::shared_ptr<PhysicalRepresentation>& physicalRepresentation) {
	this->setObject(object);
	this->setRenderer(renderer);
	this->setPhysicalRepresentation(physicalRepresentation);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::~GeometricObject_Archetype() {}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::construct() {
	return GraphicsArchetype::construct();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::update(Real dt) const {
	GraphicsArchetype::update(dt);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addPositionX(float x) {
	if ( this->object == nullptr ) return false;
	this->object->addPositionX(x);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addPositionY(float y) {
	if ( this->object == nullptr ) return false;
	this->object->addPosition(y);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addPositionZ(float z) {
	if ( this->object == nullptr ) return false;
	this->object->addPosition(z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addPosition(float x, float y, float z) {
	if ( this->object == nullptr ) return false;
	this->object->addPosition(x, y, z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addPosition(const Eigen::Vector3f& displacement) {
	if ( this->object == nullptr ) return false;
	this->object->addPosition(displacement);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPositionX(float x) {
	if ( this->object == nullptr ) return false;
	this->object->setPositionX(x);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPositionY(float y) {
	if ( this->object == nullptr ) return false;
	this->object->setPositionY(y);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPositionZ(float z) {
	if ( this->object == nullptr ) return false;
	this->object->setPositionZ(z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPosition(float x, float y, float z) {
	if ( this->object == nullptr ) return false;
	this->object->setPosition(x, y, z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPosition(const Eigen::Vector3f& position) {
	if ( this->object == nullptr ) return false;
	this->object->setPosition(position);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addRotationX(float angle) {
	if ( this->object == nullptr ) return false;
	this->object->addRotationX(angle);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addRotationY(float angle) {
	if ( this->object == nullptr ) return false;
	this->object->addRotationY(angle);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addRotationZ(float angle) {
	if ( this->object == nullptr ) return false;
	this->object->addRotationZ(angle);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addRotation(const Eigen::Quaternionf& rotation) {
	if ( this->object == nullptr ) return false;
	this->object->addRotation(rotation);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addScaleX(float x) {
	if ( this->object == nullptr ) return false;
	this->object->addScaleX(x);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addScaleY(float y) {
	if ( this->object == nullptr ) return false;
	this->object->addScaleY(y);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addScaleZ(float z) {
	if ( this->object == nullptr ) return false;
	this->object->addScaleZ(z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addScale(float x, float y, float z) {
	if ( this->object == nullptr ) return false;
	this->object->addScale(x, y, z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::addScale(const Eigen::Vector3f& scale) {
	if ( this->object == nullptr ) return false;
	this->object->addScale(scale);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setScaleX(float x) {
	if ( this->object == nullptr ) return false;
	this->object->setScaleX(x);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setScaleY(float y) {
	if ( this->object == nullptr ) return false;
	this->object->setScaleY(y);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setScaleZ(float z) {
	if ( this->object == nullptr ) return false;
	this->object->setScaleZ(z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setScale(float x, float y, float z) {
	if ( this->object == nullptr ) return false;
	this->object->setScale(x, y, z);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setScale(const Eigen::Vector3f& scale) {
	if ( this->object == nullptr ) return false;
	this->object->setScale(scale);
	return true;
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getPositionX() const {
	if ( this->object == nullptr ) return 0.0f;
	return this->object->getPositionX();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getPositionY() const {
	if ( this->object == nullptr ) return 0.0f;
	return this->object->getPositionY();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getPositionZ() const {
	if ( this->object == nullptr ) return 0.0f;
	return this->object->getPositionZ();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Eigen::Vector3f Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getPosition() const {
	if ( this->object != nullptr ) return this->object->getPosition();
	else return Eigen::Vector3f::Zero();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getScaleX() const {
	if ( this->object == nullptr ) return 1.0f;
	return this->object->getScaleX();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getScaleY() const {
	if ( this->object == nullptr ) return 1.0f;
	return this->object->getScaleY();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getScaleZ() const {
	if ( this->object == nullptr ) return 1.0f;
	return this->object->getScaleZ();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Eigen::Vector3f Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getScale() const {
	if ( this->object != nullptr ) return this->object->getScale();
	else return Eigen::Vector3f::Zero();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Eigen::Quaternionf Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getRotation() const {
	if ( this->object != nullptr ) this->object->getRotation();
	else return Eigen::Quaternionf();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Sx::Graphics::Color4f Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getColor() const {
	if ( this->object != nullptr ) return this->object->getColor();
	return Color4f();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Sx::Graphics::Color3f Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getColorSolid() const {
	if ( this->object != nullptr ) return this->object->getColorSolid();
	return Color3f();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setName(const String& name) {
	if ( this->object != nullptr ) this->object->setName(name);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setVisible(bool visible) {
	if ( this->object != nullptr ) this->object->setVisible(visible);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setSelected(bool selected) {
	if ( this->object != nullptr ) this->object->setSelected(selected);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setPointSelectionDistance(float distance) {
	if ( this->object != nullptr ) this->object->setPointSelectionDistance(distance);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::setLineSelectionDistance(float distance) {
	if ( this->object != nullptr ) this->object->setLineSelectionDistance(distance);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::show() {
	if ( this->object != nullptr ) this->object->show();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::hide() {
	if ( this->object != nullptr ) this->object->hide();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::select() {
	if ( this->object != nullptr ) this->object->select();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::deselect() {
	if ( this->object != nullptr ) this->object->deselect();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::isVisible() const {
	if ( this->object != nullptr ) return this->object->isVisible();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getPointSelectionDistance() const {
	if ( this->object != nullptr ) return this->object->getPointSelectionDistance();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
float Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getLineSelectionDistance() const {
	if ( this->object != nullptr ) return this->object->getLineSelectionDistance();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
bool Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::isSelected() const {
	if ( this->object != nullptr ) return this->object->isSelected();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
Sx::String Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::getName() const {
	if ( this->object != nullptr ) return this->object->getName();
	return String();
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::transformPointToLocal(const Eigen::Vector3f& worldPoint, Eigen::Vector3f& localPoint) {
	if ( this->object != nullptr ) return this->object->transformPointToLocal(worldPoint, localPoint);
}

template <typename GraphicsObjectType, typename Real, typename PhysicalRepresentation>
void Sx::Graphics::Archetypes::Objects::GeometricObject_Archetype<GraphicsObjectType, Real, PhysicalRepresentation>::transformLineToLocal(const Eigen::Vector3f& wPoint0, const Eigen::Vector3f& wPoint1, Eigen::Vector3f& lPoint0, Eigen::Vector3f& lPoint1) {
	if ( this->object != nullptr ) return this->object->transformLineToLocal(wPoint0, wPoint1, lPoint0, lPoint1);
}

#endif
